#include "ui_progress.h"
#include "ui_manager.h"

#include "util/timer.h"		    // Needs to come in early
#include "util/mmgr.h"		    // Needs to come in early
#include "util/common_macros.h"		// macros
#include "util/log.h"		    // logging

#include "script/scripthelper.h"
#include "script/write_lua.h"

#ifdef _ENABLE_LUABIND
#include <luabind/luabind.hpp>
#endif // _ENABLE_LUABIND


using namespace ui;
using namespace script;


UIProgress::UIProgress(UIWidget* pParent,const std::string& Name) :
	UIWidget(pParent, Name),
	m_ProgType(PROGRESS_HORZ),
	m_Progress(0.0f),
	m_Flipped(false),
	m_FlipFade(false),
	m_FullColor(0xFFFFFFFF),
	m_EmptyColor(0xFFFFFFFF),
	m_ProgEnabled(true)
{
		m_Type = WT_PROGRESS;
}

UIProgress::~UIProgress()
{

}

void		UIProgress::SetColor(float r, float g, float b, float a)
{
	UIWidget::SetColor(r, g, b, a);
	m_FullColor = m_Color;
	m_EmptyColor = m_Color;
}

bool		UIProgress::Create(const std::string& Name, const math::Vec2& Pos, const math::Vec2& Size)
{
	UIWidget::Create(Name, Pos, Size);
	// create progress stuff
	return true;
}

bool		UIProgress::Load(LuaPlus::LuaObject& _LObj)
{
	UIWidget::Load(_LObj);	// get all the common stuff loaded
	std::string	 Full = ScriptHelper::GetTableString(_LObj, "ProgressFull", "");
	std::string	 Empty = ScriptHelper::GetTableString(_LObj, "ProgressEmpty", "");

	m_FullColor = m_Color;
	m_EmptyColor = m_Color;

	float Progress = ScriptHelper::GetTableFloat(_LObj, "Progress", 0.0f);
	SetProgress(Progress);

	if (!Full.empty())
	{
			m_ImageA[WI_FULL].Create(	Full, m_BaseUV1, m_BaseUV2, false);
			//m_ImageA[WI_FULL].Tick(0);
	}

	if (!Empty.empty())
	{
			m_ImageA[WI_EMPTY].Create(	Empty, m_BaseUV1, m_BaseUV2, false);
			//m_ImageA[WI_EMPTY].Tick(0);
	}

	//m_HorizProgress = ScriptHelper::GetTableBool(_LObj, "HorizProgress");
	std::string ProgType = ScriptHelper::GetTableString(_LObj, "ProgressType");
	if (ProgType.empty())
	{
		// for backward-compatability
		if (ScriptHelper::GetTableBool(_LObj, "HorizProgress"))
			m_ProgType = PROGRESS_HORZ;
		else
			m_ProgType = PROGRESS_VERT;
	}
	else
		m_ProgType = MapStringToProgress(ProgType);

	m_Flipped		= ScriptHelper::GetTableBool(_LObj, "Flipped", false);
	m_FlipFade		= ScriptHelper::GetTableBool(_LObj, "FlipFade", m_Flipped);
	return true;
}

bool		UIProgress::ExportSpecificsToFile(script::WriteLua*	pWL)
{
	if (m_ImageA[WI_EMPTY].IsValid()) pWL->WritePair("ProgressEmpty", m_ImageA[WI_EMPTY].GetFilename());
	if (m_ImageA[WI_FULL].IsValid()) pWL->WritePair("ProgressFull", m_ImageA[WI_FULL].GetFilename());

	pWL->WritePair("Progress", GetProgress());

	//pWL->WritePair("HorizProgress", m_HorizProgress);
	pWL->WritePair("HorizProgress", (PROGRESS_HORZ == m_ProgType)); // write this for backward-compatability
	pWL->WritePair("ProgressType", MapProgressToString(m_ProgType));

	pWL->WritePair("Flipped", m_Flipped);

	if (m_ProgType >= PROGRESS_FADE)
		pWL->WritePair("FlipFade", m_FlipFade);
	return true;
}


bool		UIProgress::Tick(float dt)
{
	m_ImageA[WI_FULL].Tick(dt);
	m_ImageA[WI_EMPTY].Tick(dt);
	UIWidget::Tick(dt);	// tick children, etc
	return true;
}

bool		UIProgress::Render(bool Force)
{
	if (!m_ProgEnabled)
	{
		return UIWidget::Render(Force);
	}
	if (!Force)
	{
		// look for things that could disqualify this one from being rendered
		if (!m_IsVisible)
			return false;	// disable entire widget
		if (m_pManager->GetDragTarget() == this)
			return false;	// will get rendered on top anyways
	}

	
			// ensure it stays capped?
	// SetProgress(GetProgress());

	assert ((m_Progress >= 0.0f) && (m_Progress <= 1.0f));	// m_Progress is only set and clamped in SetProgress,
															// don't need to do clamping here -- so an assert should be enough

	math::Vec2	ClipFrom, ClipTo, OffFrom;
	float		Prog = m_Progress;
	COLOR		FullColor = m_FullColor;

	if (m_Flipped) Prog = 1.0f - Prog;
	//UTIL_CLAMP(Prog, 0.0f, 1.0f);

	if ((PROGRESS_HORZ == m_ProgType) || (PROGRESS_FADE_HORZ == m_ProgType))
	{
		ClipFrom = m_Pos;
		ClipTo = m_Pos + math::Vec2(m_Size.x * Prog, m_Size.y);
		OffFrom.x = ClipTo.x;
		OffFrom.y = ClipFrom.y;
	}
	else if ((PROGRESS_VERT == m_ProgType) || (PROGRESS_FADE_VERT == m_ProgType))
	{
		ClipFrom = m_Pos + math::Vec2(0.0f, m_Size.y * Prog);
		ClipTo = m_Pos + m_Size;
		OffFrom.x = ClipFrom.x;
		OffFrom.y = ClipTo.y;
	}

	if (m_ProgType >= PROGRESS_FADE)
	{
		float alpha = m_Progress;
		if (m_FlipFade) alpha = 1.0f - alpha;
		//UTIL_CLAMP(alpha, 0.0f, 1.0f);

		FullColor = ColorRGBA( ColorGetR(m_FullColor),
							   ColorGetG(m_FullColor),
							   ColorGetB(m_FullColor),
							   (unsigned char)(float(ColorGetA(m_FullColor)) * alpha) );
	}

	
	m_ImageA[WI_EMPTY].Setup(m_Pos, m_Size, m_Rotation, m_Scale, m_EmptyColor);
//	m_ImageA[WI_EMPTY].RenderClipped(OffFrom, m_Pos+m_Size);	// FIXME: causes aliasing artifacts
	m_ImageA[WI_EMPTY].Render();

	m_ImageA[WI_FULL].Setup(m_Pos, m_Size, m_Rotation, m_Scale, FullColor);
	if (PROGRESS_FADE == m_ProgType)
		m_ImageA[WI_FULL].Render();
	else if ((ClipFrom.x < ClipTo.x) && (ClipFrom.y < ClipTo.y))
		m_ImageA[WI_FULL].RenderClipped(ClipFrom, ClipTo);

	// render text
	m_Text.Render();


	for (ElementList::iterator It = m_Set.begin(); It != m_Set.end(); It++)
		It->second->Render();
	if (m_pManager) m_pManager->WidgetRendered();
	return true;
}

void	UIProgress::SetProgress(float f)
{
	if (f < 0.0f)
		f = 0.0f;
	else if (f > 1.0f)
		f = 1.0f;
	m_Progress = f;
}

UIWidget*	UIProgress::GetClone()
{
	UIProgress*	pNew = new UIProgress(m_pParent, GetCloneName(m_Name));
	FillCloneInfo((UIWidget*)pNew);
	//pNew->m_HorizProgress		= this->m_HorizProgress;
	pNew->m_ProgType			= this->m_ProgType;
	pNew->m_Progress			= this->m_Progress;
	pNew->m_EmptyColor			= this->m_EmptyColor;
	pNew->m_FullColor			= this->m_FullColor;
	pNew->m_Flipped				= this->m_Flipped;
	pNew->m_FlipFade			= this->m_FlipFade;
	pNew->m_ProgEnabled			= this->m_ProgEnabled;

	return pNew;
}

std::string	UIProgress::MapProgressToString(PROGRESS_TYPE t)
{
	switch (t)
	{
	case PROGRESS_HORZ:			return "horz";
	case PROGRESS_VERT:			return "vert";
	case PROGRESS_FADE:			return "fade";
	case PROGRESS_FADE_HORZ:	return "fade_horz";
	case PROGRESS_FADE_VERT:	return "fade_vert";
	}

	return "horz";
}

UIProgress::PROGRESS_TYPE	UIProgress::MapStringToProgress(const std::string& t)
{
	for (PROGRESS_TYPE i = (PROGRESS_TYPE)0; i < PROGRESS_C; i = (PROGRESS_TYPE)(i+1))
	{
		if (0 == stricmp(t.c_str(), MapProgressToString(i).c_str()))
			return i;
	}

	return PROGRESS_HORZ;
}

void	UIProgress::SetProgressType(UIProgress::PROGRESS_TYPE Type)
{
	m_ProgType = Type;
}


/// register with LUA Bind
void	UIProgress::Register(LuaPlus::LuaState* _pScript)
{
#ifdef _ENABLE_LUABIND
    lua_State * L = _pScript->GetCState ( );

	luabind::module(L)
    [

		luabind::class_<UIProgress, UIWidget >( "ProgressWidget" )
		.def( "SetProgress",			&UIProgress::SetProgress)
		.def( "GetProgress",			&UIProgress::GetProgress)
		.def( "SetEmptyImage",			&UIProgress::SetEmptyImage)
		.def( "SetFullImage",			&UIProgress::SetFullImage)
	];
#endif //_ENABLE_LUABIND
}
